/*
 * Copyright (c) 2024 iSOFT INFRASTRUCTURE SOFTWARE CO., LTD.
 * easyAda is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *          http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */

#ifndef NOTIFICAION_H
#define NOTIFICAION_H

#include <stdlib/stdint.h>

#include <tools/list.h>
#include <tools/macros.h>

#include <core/object.h>

#include <core/task.h>

typedef struct notification {
    object_t obj;
    list_t   waiters;
    unsigned long private;
    uint8_t state;
    uint8_t count;
} DEFAULT_ALINMENT notification_t;

enum ntfn_state { NTFN_IDLE = 0, NTFN_ACTIVE, NTFN_WAIT, NTFN_DIED };

enum ntfn_type { NTFN_TYPE_NORMAL = 0, NTFN_TYPE_IRQ };

static inline unsigned long notification_get_private_data(notification_t *ntfn)
{
    return ntfn->private;
}

static inline void notification_set_private_data(notification_t *ntfn, unsigned long data)
{
    ntfn->private = data;
}

static inline int notification_get(notification_t *ntfn)
{
    return object_get(&ntfn->obj);
}

static inline int notification_put(notification_t *ntfn)
{
    /* PRQA S 3432 1 # offset_of not parenthesized */
    return object_put(&ntfn->obj, offset_of(notification_t, obj), sizeof(notification_t));
}

static inline bool notification_has_waiters(notification_t *ntfn)
{
    /* PRQA S 1881 1 # unsigned == enum */
    return ntfn->state == NTFN_WAIT;
}

static inline void notification_set_state(notification_t *ntfn, uint8_t state)
{
    assert(state >= NTFN_IDLE && state <= NTFN_DIED);

    ntfn->state = state;
}

static inline void notification_init_count(notification_t *ntfn)
{
    ntfn->count = 0;
}

void notification_init(notification_t *ntfn);
void notification_wait(notification_t *ntfn, tcb_t *receiver, int block);
void notification_signal(notification_t *ntfn, tcb_t *sender);
void notification_cancel(notification_t *ntfn);

#endif
